﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NUnit.Framework;
using SistemaDeBastanteodePoderes.Persistencia;
using SistemaDeBastanteodePoderes.Dominio;

namespace SistemaDeBastanteodePoderes.Pruebas.DAO
{
    [TestFixture]
    public class Test_H1_2_ClienteDAO
    {
        ITipoEmpresaDAO tipoEmpresaDAO = null;
        IClienteDAO clienteDAO = null;
        TipoEmpresa tipoEmpresa = null;
        Cliente clienteCreado = null;

        //Para probar que traiga los representantes de un cliente
        ITipoDocumentoDAO tipoDocumentoDAO = null;
        TipoDocumento tipoDocumento = null;

        IRepresentanteDAO representanteDAO = null;
        Representante representante1 = null;
        Representante representante2 = null;

        //Para probar que traiga los bastanteos de un cliente
        ITipoServicioDAO tipoServicioDAO = null;
        TipoServicio tipoServicio = null;
        
        IPoderDAO poderDAO = null;
        Poder poder1 = null;
        Poder poder2 = null;

        ITipoIntervencionDAO tipoIntervencionDAO = null;
        TipoIntervencion tipoIntervencion = null;

        IBastanteoDAO bastanteoDAO = null;
        Bastanteo bastanteo1 = null;
        Bastanteo bastanteo2 = null;

        [TestFixtureSetUp]
        public void InicializarPruebas()
        {
            tipoEmpresaDAO = new Persistencia.NH.TipoEmpresaDAO(); // Instanciamos la implementación elegida (ADO o NHibernate)
            clienteDAO = new Persistencia.NH.ClienteDAO(); // Instanciamos la implementación elegida (ADO o NHibernate)
            foreach (Cliente cliente in clienteDAO.ListarTodos())
                clienteDAO.Eliminar(cliente);
            tipoEmpresa = tipoEmpresaDAO.Crear(new TipoEmpresa() { Abreviacion = "SAC", Descripcion = "SOCIEDAD ANONIMA CERRADA" });

            //Para probar la creacion de representantes y su uso en la clase cliente desde el ICollection
            tipoDocumentoDAO = new Persistencia.NH.TipoDocumentoDAO(); // Instanciamos la implementación elegida (ADO o NHibernate)
            representanteDAO = new Persistencia.NH.RepresentanteDAO(); // Instanciamos la implementación elegida (ADO o NHibernate)
            tipoDocumento = tipoDocumentoDAO.Crear(new TipoDocumento() { TipCorto = "XXX", TipLargo = "TRIPLE X"});

            //Para probar la creacion de bastanteo y su uso en la clase cliente desde el ICollection
            tipoServicioDAO = new Persistencia.NH.TipoServicioDAO();
            tipoServicio = tipoServicioDAO.Crear(new TipoServicio() { Servicio = "ACTIVO"});

            poderDAO =  new Persistencia.NH.PoderDAO();
            poder1 = poderDAO.Crear(new Poder(){ CodCorto = "POD01", NomPoder = "PODER 01" , Servicio = tipoServicio});
            poder2 = poderDAO.Crear(new Poder(){ CodCorto = "POD02", NomPoder = "PODER 02" , Servicio = tipoServicio});

            tipoIntervencionDAO =  new Persistencia.NH.TipoIntervencionDAO();
            tipoIntervencion = tipoIntervencionDAO.Crear(new TipoIntervencion(){ Intervencion = "A SOLA FIRMA" });

            bastanteoDAO = new Persistencia.NH.BastanteoDAO();
        }

        [Test]
        public void Test1_Crear()
        {
            // 1. Validar que ocurra un error al intentar crear un cliente con un dato nulo
            Cliente clienteACrear = new Cliente();
            clienteACrear.nroRUC = "12345678901";
            clienteACrear.razSocial = "PeruBank";
            clienteACrear.fecIniOperaciones = DateTime.Now;
            clienteACrear.cntEmpleados = 100;
            Assert.Catch<Exception>(delegate
            {
                clienteCreado = clienteDAO.Crear(clienteACrear);
            });
            // 2. Validar que se cree un cliente correctamente (sin error)
            clienteACrear.tipEmpresa = tipoEmpresa;
            Assert.DoesNotThrow(delegate
            {
                clienteCreado = clienteDAO.Crear(clienteACrear);
            });
            // 3. Validar que el cliente creado no sea nulo, tenga un código mayor a 0 y el tipo de empresa sea el ingresado
            Assert.IsNotNull(clienteCreado);
            Assert.Greater(clienteCreado.Codigo, 0);
            Assert.AreEqual(clienteCreado.tipEmpresa.Codigo, tipoEmpresa.Codigo);

            //Aca creamos nuestros representantes
            representante1 = representanteDAO.Crear(new Representante()
            {
                TipDoc = tipoDocumento,
                NroDoc = "DOC1",
                Nombres = "NOM01",
                Apellidos = "APE01",
                Cargo = "CARGO01",
                GruBastanteo = "W",
                Empresa = clienteCreado
            });
            representante2 = representanteDAO.Crear(new Representante()
            {
                TipDoc = tipoDocumento,
                NroDoc = "DOC2",
                Nombres = "NOM02",
                Apellidos = "APE02",
                Cargo = "CARGO02",
                GruBastanteo = "Z",
                Empresa = clienteCreado
            });

            //Aca creamos los bastanteos
            bastanteo1 = bastanteoDAO.Crear(new Bastanteo()
            {
                Grupo = "A",
                PoderAsignado = poder1,
                Intervencion  = tipoIntervencion,
                GruCombinacion = "",
                ImpLimite = 1000,
                FecVencimiento = DateTime.Now,
                Empresa = clienteCreado
            });

            bastanteo2 = bastanteoDAO.Crear(new Bastanteo()
            {
                Grupo = "B",
                PoderAsignado = poder2,
                Intervencion  = tipoIntervencion,
                GruCombinacion = "",
                ImpLimite = 2000,
                FecVencimiento = DateTime.Now,
                Empresa = clienteCreado
            });


        }
        [Test]
        public void Test2_Obtener()
        {
            Cliente clienteObtenido = null;
            // 1. Validar que se retorne nulo al obtener un cliente inexistente
            Assert.DoesNotThrow(delegate
            {
                clienteObtenido = clienteDAO.Obtener(1000);
            });
            Assert.IsNull(clienteObtenido);
            // 2. Validar que se obtenga el cliente creado satisfactoriamente
            Assert.DoesNotThrow(delegate
            {
                clienteObtenido = clienteDAO.Obtener(clienteCreado.Codigo);
            });
            Assert.IsNotNull(clienteObtenido);
            // 3. Validar que el ruc obtenido sea el creado anteriormente
            Assert.AreEqual(clienteObtenido.nroRUC, "12345678901");

            //4. Validamos que los representantes se encuentren en la coleccion de la clase
            Assert.GreaterOrEqual(clienteObtenido.representantes.Count, 2);
            foreach (Representante representante in clienteObtenido.representantes)
                Assert.IsNotNull(representante.Apellidos);

            //5. Validamos que los bastanteos se encuentren en la coleccion de la clase
            Assert.GreaterOrEqual(clienteObtenido.bastanteos.Count, 2);
            foreach (Bastanteo bastanteo in clienteObtenido.bastanteos)
                Assert.IsNotNull(bastanteo.Grupo);

        }
        [Test]
        public void Test3_Modificar()
        {
            Cliente clienteAModificar = clienteDAO.Obtener(clienteCreado.Codigo);
            clienteAModificar.razSocial = "PeruBank***";
            clienteAModificar.cntEmpleados = 200;
            clienteAModificar.tipEmpresa = null;
            Cliente clienteModificado = null;
            // 1. Validar que ocurrar un error al intentar modificar el cliente con un tipo de empresa nulo
            Assert.Catch<Exception>(delegate
            {
                clienteModificado = clienteDAO.Modificar(clienteAModificar);
            });
            // 2. Validar que se modifique correctamente el cliente
            clienteAModificar.tipEmpresa = tipoEmpresa;
            Assert.DoesNotThrow(delegate
            {
                clienteModificado = clienteDAO.Modificar(clienteAModificar);
            });
            // 3. Validar que el cliente modificado no sea nulo, tenga la razón social, número de empleados y tipo indicados
            Assert.IsNotNull(clienteModificado);
            Assert.AreEqual(clienteAModificar.razSocial, clienteModificado.razSocial);
            Assert.AreEqual(clienteAModificar.cntEmpleados, clienteModificado.cntEmpleados);
            Assert.AreEqual(clienteAModificar.tipEmpresa.Codigo, clienteModificado.tipEmpresa.Codigo);
        }
        [Test]
        public void Test4_Eliminar()
        {
            Cliente clienteAEliminar = clienteDAO.Obtener(clienteCreado.Codigo);
            // 1. Validar que ocurre un error si se intenta eliminar un cliente nulo
            Assert.Catch<Exception>(delegate
            {
                clienteDAO.Eliminar(null);
            });
            // 2. Validar que se elimina correctamente el cliente creado
            Assert.DoesNotThrow(delegate
            {
                clienteDAO.Eliminar(clienteAEliminar);
            });
            // 3. Validar que luego de eliminado se retorne nulo al obtenerlo
            Cliente clienteEliminado = clienteDAO.Obtener(clienteCreado.Codigo);
            Assert.IsNull(clienteEliminado);

        }
        [Test]
        public void Test5_Listar()
        {
            clienteDAO.Crear(new Cliente() { nroRUC = "A", razSocial = "A", fecIniOperaciones = DateTime.Now, tipEmpresa = tipoEmpresaDAO.Obtener(1), cntEmpleados = 10 });
            clienteDAO.Crear(new Cliente() { nroRUC = "B", razSocial = "B", fecIniOperaciones = DateTime.Now, tipEmpresa = tipoEmpresaDAO.Obtener(1), cntEmpleados = 20 });
            // 1. Validar que se listen los clientes existentes exitosamente
            ICollection<Cliente> clientesExistentes = null;
            Assert.DoesNotThrow(delegate
            {
                clientesExistentes = clienteDAO.ListarTodos();
            });
            // 2. Validar que se retornen al menos los 2 clientes creados previamente
            Assert.GreaterOrEqual(clientesExistentes.Count, 2);
            // 3. Validar que cada cliente obtenido tenga un RUC no nulo
            foreach (Cliente cliente in clientesExistentes)
                Assert.IsNotNull(cliente.nroRUC);
        }

        [TestFixtureTearDown]
        public void FinalizarPruebas()
        {
            foreach (Cliente cliente in clienteDAO.ListarTodos())
                clienteDAO.Eliminar(cliente);
            tipoEmpresaDAO.Eliminar(tipoEmpresa);

            //Esto por la creacion de representantes
            tipoDocumentoDAO.Eliminar(tipoDocumento);

            //Esto por la creacion de bastanteos
            poderDAO.Eliminar(poder1);
            poderDAO.Eliminar(poder2);
            tipoServicioDAO.Eliminar(tipoServicio);
            tipoIntervencionDAO.Eliminar(tipoIntervencion);
            
            Persistencia.NH.NHibernateHelper.CerrarFabrica();

        }
    }

}